from fastapi import (
    APIRouter, 
    Query, 
    Header,
    Cookie, 
    Path, 
    Body, 
    File,
    Form,
    status,
    Depends,
    UploadFile,
    BackgroundTasks,
)
from fastapi.responses import HTMLResponse,JSONResponse
from fastapi.encoders import jsonable_encoder
from pydantic import BaseModel, Field #, Required
from enum import Enum
from typing_extensions import Annotated
from typing import Union, List, Set, Any
from functools import lru_cache
from datetime import datetime,date

import os

from config import Settings,AgentSettings
from .Seacher import core
from celery import Celery
from dependencies import get_token_header,get_query_token


@lru_cache(maxsize=300)
def get_settings():return Settings()


settings = get_settings()


router = APIRouter(
    prefix="/sentinel",
    tags=["sentinel"],
    # dependencies=[ 
    #     Depends(get_token_header),
    #     Depends(get_query_token),
    # ],
    responses={404: {"description": "Not found"}},
)


class SearchModel(BaseModel):
    qhdm:Union[int, None] = Field(
        gt=1,
        le=82,
        default=None, 
        title="The description of the qhdm", 
    )
    sdate:Union[date, None] =  Field(
        default=None, 
        title="The description of the start date", 
        # max_length=10
    )
    edate:Union[date, None] =  Field(
        default=None, 
        title="The description of the end date", 
        # max_length=10
    )
    cloud:float = Query(ge=0.0, le=100.0)
    # tiles: List[str] = []
    # tags: Set[str] = set()
    model_config = {
        "json_schema_extra": {
            "examples": [
                {
                    "qhdm": 41,
                    "sdate": datetime.strptime("2024-03-01","%Y-%m-%d").date(),
                    "edate": datetime.strptime("2024-05-01","%Y-%m-%d").date(),
                    "cloud": 100.0,
                }
            ]
        }
    }


class CoperniDownLoadModel(BaseModel):
    base_query: Union[SearchModel, None] = None
    save_dir: Union[str, None] =  Field(
        default='/data/ygjsb/Backup/MonthSentinelZip', 
        title="The description of the save floder", 
        max_length=500
    )


class TileSearchModel(BaseModel):
    tile:Union[str, None] = Field(
        default=None, 
        title="哨兵图幅号", 
        max_length=5
    )
    sdate:Union[date, None] =  Field(
        default=None, 
        title="起始日期", 
        # max_length=10
    )
    edate:Union[date, None] =  Field(
        default=None, 
        title="结束日期", 
        # max_length=10
    )
    cloud:Union[float, None] = Field(
        default=100, 
        ge=0.0, 
        le=100.0
    )
    # agent:Union[AgentSettings, None] = settings.agent
    model_config = {
        "json_schema_extra": {
            "examples": [
                {
                    "tile": "50SLH",
                    "sdate": datetime.strptime("2024-03-01","%Y-%m-%d").date(),
                    "edate": datetime.strptime("2024-05-01","%Y-%m-%d").date(),
                    "cloud": 100.0,
                    # "agent": settings.agent.dict(),
                }
            ]
        }
    }


class TileDateSearch:
    def __init__(
        self, 
        tile:str='50SLH',
        sdate:str='2024-03-01',
        edate:str='2024-04-01',
        cloud:float=100.0,
    ):
        self.tile = tile
        self.sdate = sdate
        self.edate = edate
        self.cloud = cloud
        # self.agent = agent


class CopernicusAccount(BaseModel):
    username: Union[str, None] = None
    password: Union[str, None] = None


class AgentFolderModel(BaseModel):
    host:Union[str,None] =Field(
        default="192.168.2.172", 
        title="The description of the item", 
        max_length=15
    )
    port:int=Field(
        default=10809, 
        title="The description of the item", 
        ge=0, 
        le=65536
    )
    folder:str=Field(
        default=r"/data/ygjsb/Backup/MonthSentinelZip", 
        title="The description of the item", 
        max_length=300
    )
        

class ExtraModel(BaseModel):
    agent:Union[str,None]
    # = Field(
    #     default=settings.agent, 
    #     title="The description of the save floder", 
    #     # max_length=500
    # )
    # agent:Union[AgentSettings, None] = Field(
    #     default=settings.agent, 
    #     title="The description of the save floder", 
    #     # max_length=500
    # )
    save_dir:Union[str,None]
    # = Field(
    #     default='/data/ygjsb/Backup/MonthSentinelZip', 
    #     title="The description of the save floder", 
    #     max_length=500
    # )
    # save_dir: Union[str, None] = Field(
    #     default='/data/ygjsb/Backup/MonthSentinelZip', 
    #     title="The description of the save floder", 
    #     max_length=500
    # )


class ResponseDownload(BaseModel):
    username: Union[str, None]
    password: Union[str, None]
    query_params: Union[TileSearchModel,None]
    extra_params: Union[ExtraModel,None]
  

class AccountId(str, Enum):
    item_id1 = "fyy1"
    item_id2 = "fyy2"
    item_id3 = "ft1"
    item_id4 = "ft2"


# 表单和请求体不要一起使用
async def download_zipfile_parameters(
    extra: Annotated[
        AgentFolderModel, 
        Body(
            title="代理和目录", 
            embed=True,
        )
    ],
    account_id: Annotated[
        int,  
        Path(
            # default = 2,  # ...
            # required=True,
            title="账户索引id",
            # min_length=3, 
            # max_length=50
        )
    ],
    # username: Annotated[Union[str, None],Form()] = "sadfa", 
    # password: Annotated[Union[str, None],Form()] = "dasdf",
    ads_id: Annotated[
        Union[str, None], 
        Cookie()
    ] = "dasdfa",
    user_agent: Annotated[
        Union[str, None], 
        Header()
    ] = "asdfsad",
    tile: Annotated[
        Union[str, None], 
        Query(
            # default = "50SLH",
            # alias="item-query",
            title="查询参数", 
            embed=True,
            required=True,
        )
    ] = "50SLH",
    sdate: Annotated[
        Union[date, str, None], 
        Query(
            # default = ...,
            # alias="item-query",
            title="开始日期", 
            embed=True,
            required=True,
        )
    ] = "2024-04-01",
    edate: Annotated[
        Union[date, str, None], 
        Query(
            # default = ...,
            # alias="item-query",
            title="结束日期", 
            embed=True,
            required=True,
        )
    ] = "2024-05-01",
    cloud: Annotated[
        Union[float, None], 
        Query(
            # default = 100.0,
            # alias="item-query",
            title="最大云量", 
            embed=True,
            required=True,
        )
    ] = 100.0,
):
    return {"q": tile, "sdate": sdate, "edate": edate, "cloud": cloud}


accounts = {
    "fyy1": {"username": "fyy0395@gmail.com", "password": 'Fengyy.013579'},
    "fyy2": {"username":"10415326215@qq.com", "password":"Fengyy.013579"},
    "ft1": {"username":"fengting2114@gmail.com", "password":"FF17783625tt."},
    "ft2": {"username":"fengting2112@gmail.com",  "password":"FF17783625tt."},
}

# 路径参数不能设置默认值
# 请求体 + 路径参数(枚举) + 查询参数（模型） 例子,
@router.post(
    "/download/{account_id}",
    summary="从官网下载哨兵数据",
    status_code=status.HTTP_201_CREATED,
    response_description="copernicus账户详细信息",
    # response_model=ResponseDownload,
    deprecated=False,  # 是否启用
)
async def download_zipfile(commons: dict = Depends(download_zipfile_parameters,use_cache=False)):
    """
    下载哨兵数据
    - **account_id**: 账户索引
    - **query_params**: 查询参数
    - **extra_params**: 查询参数
    """
    print(commons)
    # print(query_params.dict())
    # print(extra_params.dict())
    return {"messge": "success"}


@router.put("/search",summary="从官网查询哨兵数据")
async def search_product(b: TileDateSearch=Depends()) :# -> Any
    """
    下载哨兵数据
    - **b**: 查询参数
    """
    print(b.cloud)
    content = {"msg":"success"}   
    return JSONResponse(status_code=status.HTTP_201_CREATED, content=content)


@router.post(
    "/account_search/{item_id}",
    summary="查询copernicus账户",
    # description="根据item_id 查询相应的copernicus账户详细信息",  # 与函数注释互斥
    response_description="copernicus账户详细信息",
    response_model=CopernicusAccount,
    deprecated=False,  # 是否启用
)
async def daemon(item_id: AccountId) -> Any:
    """
    查询copernicus账户参数
    - **item_id**: 查询参数
    """
    return accounts[item_id]


@router.put(
    "/account_update/{item_id}",
    summary="更新copernicus账户",
    response_model=CopernicusAccount
)
async def update_item(item_id: str, account: Annotated[CopernicusAccount,"The size can"]):
    update_account_encoded = jsonable_encoder(account)
    accounts[item_id] = update_account_encoded
    print(update_account_encoded)
    return update_account_encoded


@router.get(
    "/files/{file_path:path}",
    summary="传递文件路径参数",
    response_description="文件路径信息",
    deprecated=False,  # 是否启用
)
async def read_file(file_path: str):
    """
    测试传递文件路径
    - **file_path**: 文件路径
    """
    return {"file_path": file_path}


@router.get(
    "/users/{user_id}/items/{item_id}",
    summary="测试多路径参数",
    deprecated=False,  # 是否启用
)
async def read_user_item(
    user_id: int, 
    item_id: str, 
    q: Union[str, None] = None, 
    short: bool = False
):
    item = {"item_id": item_id, "owner_id": user_id}
    if q:
        item.update({"q": q})
    if not short:
        item.update(
            {"description": "This is an amazing item that has a long description"}
        )
    return item


@router.get("/raster",summary="上传哨兵数据")
async def upload_zipfile(
    files: List[UploadFile]= File(description="Multiple files as UploadFile"),
    save_dir: str = Form(default='/data/fengyy/dateset/upload'),):
    for fileobject in files:
        filepath = os.path.join(save_dir,fileobject.filename)
        if not os.path.exists(filepath):
            with open(filepath,"wb") as file_handle:
                contents = await fileobject.read()
                file_handle.write(contents)
    content = {"msg":"success"}          
    return JSONResponse(status_code=status.HTTP_201_CREATED, content=content)
